#include <iostream>
#include <list>

#include <boost/shared_ptr.hpp>

struct Person
{
  std::string name;
  std::size_t age;

  Person(const std::string n, std::size_t a)
    : name(n), age(a)
  { }
};


typedef boost::shared_ptr<Person> PersonPtr;
typedef std::list<PersonPtr> PersonList;
typedef boost::shared_ptr<PersonList> PersonListPtr;

std::ostream&
operator<< (std::ostream& os, const PersonList& list)
{
  for (PersonList::const_iterator it = list.begin(); it != list.end(); ++it)
    {
      os << "(" << (*it)->name << ", " << (*it)->age << "); ";
    }
  return os;
}

int main()
{
  PersonPtr p1(new Person("Person1", 20));
  PersonPtr p2(new Person(*p1));

  std::cerr << "before: " << std::endl;
  std::cerr << "p1: " << p1->name << " " << p1->age << std::endl;  
  std::cerr << "p2: " << p2->name << " " << p2->age << std::endl;

  p2->age = 30;

  std::cerr << "after: " << std::endl;
  std::cerr << "p1: " << p1->name << " " << p1->age << std::endl;  
  std::cerr << "p2: " << p2->name << " " << p2->age << std::endl;

  PersonListPtr list1(new PersonList);
  list1->push_back(p1);
  list1->push_back(p2);

  PersonListPtr list2(new PersonList(*list1));
  PersonList::iterator it = list2->begin();
  
  (*it)->age = 40;

  PersonListPtr list3(new PersonList);
  for (PersonList::const_iterator jt = list1->begin(); jt != list1->end(); ++jt)
    {
      PersonPtr new_p(new Person(**jt));
      list3->push_back(new_p);
    }

  it = list3->begin();
  (*it)->age = 50;

  std::cerr << "list1: " << *list1 << std::endl;
  std::cerr << "list2: " << *list2 << std::endl;
  std::cerr << "list3: " << *list3 << std::endl;
}
